<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>组件component-混入minxin</title>
</head>
<body>
<div id="app">
  <!-- 全局组件   -->
  <cxp_p v-for='(y,i) in list' :canshu="y.age" v-bind:key="i" @bbb="cxp_pZi($event)">
    <slot><li>组件上的插槽</li></slot>
    <slot b-slot='chacao'><li>具名插槽，有名字的插槽</li></slot>
  </cxp_p>
  <!-- 局部组件 -->
  <my-components></my-components>
  <!--is  用于动态组件且基于 DOM 内模板的限制来工作
      component 渲染一个“元组件”为动态组件。依 is 的值，来决定哪个组件被渲染
      keep-alive 包裹动态组件时，会缓存不活动的组件实例，而不是销毁它们
      -->
  <table>
    <!-- my-components即使放在table里,也可能无效,会被渲染到table外面 -->
    <my-components />
    <tr is="my-components"></tr>
  </table>
  <keep-alive>
    <component v-bind:is="dt"></component>
  </keep-alive>

</div>

<!-- 全局组件 -->
<div class="tem">
  {{msg}}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  // 注册组件(必须要在创建Vue实例之前)
  // 全局组件(只要在vue实例元素里就能使用,不用再局部注册) [组件名称*(使用时的元素名),组件配置]
  Vue.component('cxp_p', {
    props: ['canshu'], // 使用组件时上的元素属性,通过此实现父向子传值 字母不要用大写
    // 模板 最外层不能存在两个元素 必须有一个根节点
    //    slot 插槽,父传递给子的内容 无name代表default
    template: `<ol>
                <li @click="a">这是全局组件上的内容{{count}}{{cxp_p_msg}}</li>
                <li>这是父传给子的内容{{canshu}}</li>
                <li @click='b'>子传个父一个点击事件,子向父传值</li>
                <slot></slot>
                <slot name='chacao'></slot>
              </ol>`,
    // data使用函数返回值,运用闭包原理防止组件被多次调用时,改一发而动全身,不要在外面定义一个对象
    data:function () {
      return {
        cxp_p_msg: "这是模板里的数据",
        count: 0,
      }
    },
    methods:{
      a(){
        console.log(this.count++)
      },
      // $emit 暴露给父级一个方法名 子级触发了这个函数时,父级使用暴露的方法名来进行监听
      b(){
        this.$emit('bbb','第二个参数是子暴露给父的值')
      }
    },
  });

  //创建一个组件需要的对象 局部注册时,组件第二个参数是个对象,可以用这个对象替代它
  let com = {
    props: ['canShu'],
      //模板 最外层不能存在两个元素 必须有个根节点
      template: `<ul>
                <li @click="a">这是局部组件上的内容{{count}}{{cxp_p_msg}}</li>
                <li>这是组件上的内容{{canShu}}:{{canShu}}</li>
              </ul>`,
    //data使用函数返回值 运用闭包原理防止组件被多次调用时 该一发而动全身
    data:function () {
      return {
        cxp_p_msg: "这是模板里的数据",
        count: 0,
      }
    },
    methods:{
      a(){
        console.log(this.count++)
      }
    },
  }

  new Vue({
    el: '#app',
    data:{
      list: [
        {name: "chen", age: 21},
        {name: "chen", age: 22},
        {name: "chen", age: 23},
      ],
      dt:"my-components"
    },
    //局部组件 只有在当前vue实例(#app)里才能使用
    components:{
      'my-components' : com
    },
    methods:{
      cxp_pZi(e){
        console.log(e)
      }
    },
  });
  
  // 混入 一个混入对象可以包含任意组件选项 一定要在实例之前定义
  //   当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项,
  //   组件本身定义的选项会与minxin合并,引用类型内部会递归合并,发生冲突时组件数据优先
  //   同名钩子函数将合并为一个数组,都将被调用,混入对象的钩子将在组件自身钩子之前调用
  //   全局注册Vue.mixin({data:{}}) 的会影响每个之后创建的Vue实例,即使他们没在选项里写
  var myMixin = { // 定义一个混入对象
    data: function () {
      return {
        foo: '混入里的值',
        msg:"a"
      }
    }
  }

  // template模板(不推荐在vue实例中使用) 会把挂载的元素(.tem)关掉显示模板里的东西
  //   el就是告诉template模板覆盖到哪个元素上去，没有el他就不会覆盖(模板内代码不生效)
  let vTem = new Vue({
    el: '.tem',
    data:{
      msg: 'dd'
    },
    template:'<div>{{msg}}{{foo}},已将原来的元素覆盖</div>',
    mixins: [myMixin]
  })
</script>
</body>
</html>